/*-
 * $Id: Terminal.java 4 2010-11-04 07:39:56Z andrewbass $
 */

package com.google.code.getwrong.terminalui;

import static com.google.code.getwrong.terminalui.TerminalMain.ESC;
import static java.lang.System.getProperty;
import static java.nio.charset.Charset.forName;
import static java.util.Arrays.asList;

import java.io.PrintWriter;
import java.util.List;

/**
 * @author Andrew ``Bass'' Shcheglov (andrewbass@gmail.com)
 * @author $Author: andrewbass $
 * @version $Revision: 4 $, $Date:: 2010-11-04 07:39:56 +0000 #$
 * @todo support fg/bg restore.
 * @todo support cursor position restore.
 */
public final class Terminal {
	private final PrintWriter out;

	private final boolean supports256Colors;

	/**
	 * @param out
	 * @param supports256Colors
	 */
	public Terminal(final PrintWriter out,
			final boolean supports256Colors) {
		this.out = out;
		this.supports256Colors = supports256Colors;
	}


	/**
	 * @param x
	 * @see PrintWriter#println(String)
	 */
	public void println(final String x) {
		this.out.println(x);
	}

	/**
	 * @see PrintWriter#println()
	 */
	public void println() {
		this.out.println();
	}

	/**
	 * @param c
	 * @see PrintWriter#print(char)
	 */
	public void print(final char c) {
		this.out.print(c);
	}

	/**
	 * @see PrintWriter#flush()
	 */
	public void flush() {
		this.out.flush();
	}

	public boolean supportsPseudoGraphics() {
		final List<String> supportedCharsets = asList("IBM437", "IBM866", "KOI8-R", "UTF-8");
		return supportedCharsets.contains(forName(getProperty("file.encoding")).name());
	}

	public boolean supports256Colors() {
		return this.supports256Colors;
	}


	/**
	 * ^[[H^[[2J.
	 */
	public void clear() {
		this.out.append(ESC).append('[');
		this.out.append('H'); // Move to 0, 0
		this.out.append(ESC).append('[');
		this.out.append("2J"); // Erase display
		this.out.flush();
	}

	/**
	 * @param x column number, starting from 0
	 * @param y line number, starting from 0
	 */
	public void moveTo(final int x, final int y) {
		if (x < 0 || y < 0) {
			throw new IllegalArgumentException();
		}

		this.out.append(ESC).append('[');
		this.out.append(String.valueOf(y + 1)).append(';').append(String.valueOf(x + 1)).append('H');
		this.out.flush();
	}

	public void setGraphicsMode(final int ... attributes) {
		if (attributes.length == 0) {
			return;
		}

		this.out.append(ESC).append('[');
		for (int i = 0; i < attributes.length; i++) {
			final String attribute = String.valueOf(attributes[i]);
			this.out.append(String.valueOf(attribute)).append(i + 1 < attributes.length ? ';' : 'm');
		}
		this.out.flush();
	}

	/**
	 * @param foreground
	 */
	public void setForeground(final Color foreground) {
		this.setGraphicsMode(foreground.getForegroundAttributes(this));
	}

	/**
	 * @param background
	 */
	public void setBackground(final Color background) {
		this.setGraphicsMode(background.getBackgroundAttributes(this));
	}
}
